package com.dsl.service;

import com.dsl.entity.User;
import com.dsl.utils.CommunityConstant;
import com.dsl.utils.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Description 关注业务类
 * @Author dsl
 * @Date 2024/9/14 上午10:58
 * @Version 1.0
 */
@Service
public class AttentionService implements CommunityConstant {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    //关注
    public void attention(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {

                String attentionKey = RedisKeyUtil.getAttenetionKey(userId, entityType);
                String fansKey = RedisKeyUtil.getFansKey(entityType, entityId);

                operations.multi();//事务开始

                operations.opsForZSet().add(attentionKey, entityId, System.currentTimeMillis());
                operations.opsForZSet().add(fansKey, userId, System.currentTimeMillis());

                return operations.exec();//执行事务内语句
            }
        });
    }

    //取消关注
    public void unattention(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {

                String attentionKey = RedisKeyUtil.getAttenetionKey(userId, entityType);
                String fansKey = RedisKeyUtil.getFansKey(entityType, entityId);

                operations.multi();//事务开始

                operations.opsForZSet().remove(attentionKey, entityId);
                operations.opsForZSet().remove(fansKey, userId);

                return operations.exec();//执行事务内语句
            }
        });
    }

    //查询关注的实体的数量
    public long getAttentionCount(int userId, int entityType){
        String attentionKey = RedisKeyUtil.getAttenetionKey(userId, entityType);
        return redisTemplate.opsForZSet().zCard(attentionKey);
    }

    //查询实体的粉丝数量
    public long getFansCount(int entityType, int entityId){
        String fansKey = RedisKeyUtil.getFansKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(fansKey);
    }

    //查询当前用户是否已关注该实体
    public boolean hasAttentioned(int userId, int entityType, int entityId){
        String attentionKey = RedisKeyUtil.getAttenetionKey(userId, entityType);
        return redisTemplate.opsForZSet().score(attentionKey, entityId) != null;
    }

    //查询某用户关注的人(支持分页)
    public List<Map<String, Object>> getAttention(int userId, int offset, int limit){

        String attentionKey = RedisKeyUtil.getAttenetionKey(userId, ENTITY_TYPE_USER);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(attentionKey, offset, offset + limit - 1);

        if(targetIds == null){
            return null;
        }
        List<Map<String, Object>> list = new ArrayList<>();
        for(Integer targetId : targetIds){
            Map<String, Object> map = new HashMap<>();
            User user = userService.getUserById(targetId);
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(attentionKey, targetId);
            map.put("attentionTime", new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }

    //查询某个用户的粉丝
    public List<Map<String, Object>> getFans(int userId, int offset, int limit){
        String fansKey = RedisKeyUtil.getFansKey(ENTITY_TYPE_USER, userId);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(fansKey, offset, offset + limit - 1);

        if(targetIds == null){
            return null;
        }

        List<Map<String, Object>> list = new ArrayList<>();
        for(Integer targetId : targetIds){
            Map<String, Object> map = new HashMap<>();
            User user = userService.getUserById(targetId);
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(fansKey, targetId);
            map.put("attentionTime", new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }


}
